package com.yfp.operation.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.shortlink.GenerateShortLinkRequest;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.poi.excel.ExcelReader;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.util.StringUtil;
import com.google.zxing.WriterException;
import com.yfp.common.core.domain.R;
import com.yfp.common.core.utils.poi.ExcelUtil;
import com.yfp.common.core.web.controller.BaseController;
import com.yfp.common.core.web.page.TableDataInfo;
import com.yfp.common.log.annotation.Log;
import com.yfp.common.log.enums.BusinessType;
import com.yfp.operation.config.WxMaConfiguration;
import com.yfp.operation.config.WxPayProperties;
import com.yfp.operation.domain.MarCoupon;
import com.yfp.operation.domain.Marketing;
import com.yfp.operation.domain.MiniBanner;
import com.yfp.operation.domain.Template;
import com.yfp.operation.domain.dto.*;
import com.yfp.operation.domain.vo.*;
import com.yfp.operation.service.MarCouponDirectionalService;
import com.yfp.operation.service.MarCouponService;
import com.yfp.operation.service.MarketingService;
import com.yfp.operation.service.MiniBannerService;
import com.yfp.operation.utils.QRCodeAndZipUtils;
import com.yfp.operation.domain.dto.*;
import com.yfp.operation.domain.vo.*;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 *
 * @version 1.0
 * @date 2024-07-13 11:46
 */
@RestController
@RequestMapping("/marCoupon")
@Tag(name = "优惠券-pc")
@Slf4j
public class MarCouponController extends BaseController {

    @Resource
    private MarCouponService marCouponService;
    @Autowired
    private WxPayProperties wxPayProperties;
    @Autowired
    private MiniBannerService miniBannerService;
    @Resource
    private MarCouponDirectionalService marCouponDirectionalService;
    @Resource
    private MarketingService marketingService;

    /**
     * 新增活动
     *
     * @param marCoupon
     * @return
     */
    @PostMapping("add")
    @Operation(summary = "新增优惠券")
    public R<Void> addMarCoupon(@RequestBody MarCoupon marCoupon) {
        return marCouponService.addMarCoupon(marCoupon);
    }


    /**
     * 多条件查询活动列表
     *
     * @param
     * @return
     */
    @GetMapping("")
    @Operation(summary = "多条件查询优惠券列表")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successful response", content = @Content(mediaType = "application/json", schema = @Schema(implementation = MarCouponVO.class)))})
    public R<TableDataInfo> getMarCoupon(CouponQueueDTO couponQueueDTO) {
        startPage();
        List<MarCouponVO> marCouponVOS = marCouponService.selectMarCoupon(couponQueueDTO);
        TableDataInfo dataTable = getDataTable(marCouponVOS);
        List<MarCouponVO> marCouponVOList = marCouponService.complementListData(marCouponVOS);
        dataTable.setRows(marCouponVOList);
        return R.ok(dataTable);
    }


    /**
     * 套餐列表-数据API
     *
     * @return
     */
    @GetMapping("/data")
    @Operation(summary = "数据API")
    public R<MarCouponDataVO> detailMarCoupon(Long couponId) {
        return marCouponService.getMarCouponData(couponId);
    }


    /**
     * 修改活动状态
     *
     * @return
     */
    @DeleteMapping("")
    @Log(title = "pc-修改优惠券状态", businessType = BusinessType.UPDATE)
    @Operation(summary = "删除优惠券")
    public R<Void> deleteMarCoupon(@RequestParam("couponId") Long couponId, @RequestParam("status") Integer status) {
        marCouponService.deleteMarCoupon(couponId, status);
        return R.ok();
    }


    /**
     * 领取优惠券列表
     *
     * @return
     */
    @GetMapping("/acquire")
    @Operation(summary = "领取优惠券列表")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successful response", content = @Content(mediaType = "application/json", schema = @Schema(implementation = AcquireListVO.class)))})
    public R<TableDataInfo> acquireCouponList(AcquireCouponDTO acquireCouponDTO) {
        startPage();
        List<AcquireListVO> list = marCouponService.acquireCouponList(acquireCouponDTO);
        TableDataInfo dataTable = getDataTable(list);
        List<AcquireListVO> acquireListVOS = marCouponService.acquireCouponListomplement(list,acquireCouponDTO);
        dataTable.setRows(acquireListVOS);
        return R.ok(dataTable);
    }

    /**
     * 导出领取优惠券列表
     *
     * @return
     */
    @PostMapping("/exportAcquire")
    @Operation(summary = "导出领取优惠券列表", description = "数据导出")
    public void exportAcquire(HttpServletResponse response, @ModelAttribute AcquireCouponDTO acquireCouponDTO) {
        List<AcquireListVO> list = marCouponService.acquireCouponList(acquireCouponDTO);
        List<AcquireListVO> acquireListVOS = marCouponService.acquireCouponListomplement(list,acquireCouponDTO);
        ExcelUtil<AcquireListVO> util = new ExcelUtil<>(AcquireListVO.class);
        util.exportExcel(response, acquireListVOS, "领取优惠券");
    }

    /**
     * 根据优惠券id获取数据
     *
     * @param couponId
     * @return
     */
    @GetMapping("/id")
    @Operation(summary = "根据优惠券id获取数据")
    public R<MarCoupon> getById(Long couponId) {
        MarCoupon marCoupon = marCouponService.selectById(couponId);
        return R.ok(marCoupon);
    }


    /**
     * 发放优惠券
     *
     * @param couponIds
     * @return
     */
    @PostMapping("/grant")
    @Log(title = "pc-发放优惠券", businessType = BusinessType.INSERT)
    @Operation(summary = "发放优惠券")
    public R<List<GrantDetailVO>> grant(@RequestBody List<Long> couponIds) {
        return marCouponService.grant(couponIds);
    }


    /**
     * 进行中优惠券列表
     */
    @GetMapping("/list")
    @Operation(summary = "进行中优惠券列表")
    public R<List<MarCouponVO>> getByTypeMarCoupon(CouponQueueDTO couponQueueDTO) {
        return marCouponService.getByTypeMarCoupon(couponQueueDTO);
    }


    @PostMapping("/groupList")
    @Operation(summary = "查询分组进行中优惠券列表")
    public R<List<GroupMarCouponVO>> groupList(@RequestBody GroupCouponListDTO groupCouponListDTO) {
        R<List<MarCouponVO>> byTypeMarCoupon = marCouponService.groupCouponList(groupCouponListDTO);

        List<MarCouponVO> marCouponVOS = byTypeMarCoupon.getData();
        if (groupCouponListDTO.getPosition() != null && groupCouponListDTO.getPosition() == 1) {
            groupCouponListDTO.setPosition(0);
            // 获取普通全部优惠券
            List<MarCouponVO> list = marCouponService.getByPositionAndCityName(groupCouponListDTO);
            marCouponVOS.addAll(list);
        }
        if (groupCouponListDTO.getPosition() != null && groupCouponListDTO.getPosition() == 3) {
            groupCouponListDTO.setPosition(2);
            // 获取特殊全部优惠券
            List<MarCouponVO> list = marCouponService.getByPositionAndCityName(groupCouponListDTO);
            marCouponVOS.addAll(list);
        }

        List<MarCouponVO> manjians = marCouponVOS.stream().filter(s -> s.getType() == 1).collect(Collectors.toList());
        List<MarCouponVO> zhekous = marCouponVOS.stream().filter(s -> s.getType() == 2).collect(Collectors.toList());
        List<MarCouponVO> danpins = marCouponVOS.stream().filter(s -> s.getType() == 3).collect(Collectors.toList());
        List<MarCouponVO> xinrens = marCouponVOS.stream().filter(s -> s.getType() == 4).collect(Collectors.toList());
        List<MarCouponVO> bawangs = marCouponVOS.stream().filter(s -> s.getType() == 5).collect(Collectors.toList());
        List<GroupMarCouponVO> groupMarCouponVOS = new ArrayList<>();
        GroupMarCouponVO groupMarCouponVO = new GroupMarCouponVO();
        groupMarCouponVO.setType(1);
        groupMarCouponVO.setTypeName("满减券");
        groupMarCouponVO.setMarCouponVOList(manjians);

        GroupMarCouponVO groupMarCouponVO2 = new GroupMarCouponVO();
        groupMarCouponVO2.setType(2);
        groupMarCouponVO2.setTypeName("折扣券");
        groupMarCouponVO2.setMarCouponVOList(zhekous);

        GroupMarCouponVO groupMarCouponVO3 = new GroupMarCouponVO();
        groupMarCouponVO3.setType(3);
        groupMarCouponVO3.setTypeName("单品券");
        groupMarCouponVO3.setMarCouponVOList(danpins);

        GroupMarCouponVO groupMarCouponVO4 = new GroupMarCouponVO();
        groupMarCouponVO4.setType(4);
        groupMarCouponVO4.setTypeName("新人券");
        groupMarCouponVO4.setMarCouponVOList(xinrens);

        GroupMarCouponVO groupMarCouponVO5 = new GroupMarCouponVO();
        groupMarCouponVO5.setType(5);
        groupMarCouponVO5.setTypeName("霸王免单券");
        groupMarCouponVO5.setMarCouponVOList(bawangs);

        groupMarCouponVOS.add(groupMarCouponVO);
        groupMarCouponVOS.add(groupMarCouponVO2);
        groupMarCouponVOS.add(groupMarCouponVO3);
        groupMarCouponVOS.add(groupMarCouponVO4);
        groupMarCouponVOS.add(groupMarCouponVO5);
        return R.ok(groupMarCouponVOS);
    }

    /**
     * 延长时间
     */
    @PostMapping("/lengthen")
    @Log(title = "pc-延长时间", businessType = BusinessType.UPDATE)
    @Operation(summary = "延长时间")
    public R<Void> lengthen(@RequestBody LengthenDateDTO lengthenDateDTO) {
        marCouponService.lengthen(lengthenDateDTO);
        return R.ok();
    }


    @PostMapping("/exportLengthen")
    @Log(title = "pc-导出单个延长时间", businessType = BusinessType.UPDATE)
    @Operation(summary = "导出单个延长时间")
    public R<Void> exportLengthen(@RequestBody LengthenDateDTO lengthenDateDTO) {
        marCouponService.exportLengthen(lengthenDateDTO);
        return R.ok();
    }


    @GetMapping("/generateShortLink")
    @Operation(summary = "获取小程序分享短链接")
    public R<String> generateUrlLink(Long marketingId) {
        String shortLink = "";
        try {
            Marketing marketing = marketingService.getById(marketingId);
            String pagesUrl = "pagesMy/collarcenter/collarcenter";
            switch (marketing.getType()) {
                case 3:
                    pagesUrl = "pagesMy/giftPackage/giftPackage";
                    break;
            }
            MiniBanner miniBanner = miniBannerService.findLastByMarketingId(marketingId);

            // 有banner就取
            if (BeanUtil.isEmpty(miniBanner)) {
                if (marketing.getType() == 1) {
                    // 判断是否配置活动背景，没配跳领券中心，配了跳活动通用页面
                    MarCoupon marCoupon = marCouponService.getById(marketing.getMarCouponId());
                    if (!StringUtil.isEmpty(marCoupon.getBackgroundImg())) {
                        pagesUrl = "pagesMy/InviteRegister/InviteRegister";
                    }
                } else if (marketing.getType() == 3) {
                    pagesUrl = "pagesMy/InviteRegister/InviteRegister";
                }
            } else {
                if (!StringUtil.isEmpty(miniBanner.getUrl()) && !miniBanner.getUrl().startsWith("http")) {
                    pagesUrl = miniBanner.getUrl().startsWith("/") ? miniBanner.getUrl().substring(1) : miniBanner.getUrl();
                }
            }

            pagesUrl = pagesUrl + "?marketingId=" + marketingId;
            logger.info("获取小程序分享短链接-> pagesUrl: {}", pagesUrl);
            final WxMaService wxMaService = WxMaConfiguration.getMaService(wxPayProperties.getConfigs().get(0).getAppId());
            GenerateShortLinkRequest shortLinkRequest = GenerateShortLinkRequest.builder().pageUrl(pagesUrl).build();
            shortLink = wxMaService.getLinkService().generateShortLink(shortLinkRequest);
        } catch (Exception e) {
            return R.fail(e.getMessage());
        }
        return R.ok(shortLink);
    }


    /**
     * 导出详情
     *
     * @param acquireCouponDTO
     * @return
     */
    @GetMapping("/derivedetail")
    @Operation(summary = "导出详情")
    @ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Successful response", content = @Content(mediaType = "application/json", schema = @Schema(implementation = DeriveDetailVO.class)))})
    public R<TableDataInfo> deriveDetail(AcquireCouponDTO acquireCouponDTO) {
        startPage();
        List<DeriveDetailVO> list = marCouponService.deriveDetail(acquireCouponDTO);
        TableDataInfo dataTable = getDataTable(list);
        return R.ok(dataTable);
    }


    /**
     * 导出
     *
     * @param couponDeriveDTO
     */
    @PostMapping("/derive")
    @Operation(summary = "导出")
    public void derive(@ModelAttribute CouponDeriveDTO couponDeriveDTO, HttpServletResponse response) {
        String fileName = "优惠券.zip";
        File file = new File(fileName);
        try {
            List<String> ids = marCouponService.derive(couponDeriveDTO);
            if (CollectionUtils.isEmpty(ids)) {
                return;
            }
            log.info("ids", JSONObject.toJSONString(ids));
            QRCodeAndZipUtils.addFilesToZip(fileName, ids);
//            file = new File(fileName);
            // 设置响应头
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            // 将文件写入响应流
//            OutputStream out = response.getOut();
            OutputStream out = response.getOutputStream();
            FileInputStream fis = new FileInputStream(file);
            byte[] buffer = new byte[1024 * (ids.size() / 100 + 1)];
            Integer len;
            while ((len = fis.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
        } catch (FileNotFoundException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (WriterException e) {
            throw new RuntimeException(e);
        } finally {
            try {
                if (null != file && file.exists()) {
                    file.delete();
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }


    /**
     * 导出列表失效
     *
     * @param checkId
     * @return
     */
    @PutMapping("/invalid")
    @Log(title = "pc-导出列表失效", businessType = BusinessType.UPDATE)
    @Operation(summary = "导出列表失效")
    public R<Void> invalid(@RequestParam("checkId") @Schema(description = "券码id") String checkId) {
        marCouponService.invalid(checkId);
        return R.ok();
    }


    @PutMapping("/inviteinvalid")
    @Log(title = "pc-领取列表失效", businessType = BusinessType.UPDATE)
    @Operation(summary = "领取列表失效")
    public R<Void> inviteinvalid(@RequestParam("clientCouponId") @Schema(description = "领券id") Long clientCouponId) {
        marCouponService.inviteinvalid(clientCouponId);
        return R.ok();
    }

    @GetMapping("check/combo/participation")
    @Operation(summary = "检测该套餐是否参与")
    public R<Boolean> checkComboParticipation(@RequestParam("comboId") String comboId) {
        return R.ok(marCouponService.checkComboParticipation(comboId));
    }


    @PostMapping("/template")
    @Operation(summary = "模板下载")
    public void machineExport(HttpServletResponse response) {
        ArrayList<Template> list = new ArrayList<>();
        ExcelUtil<Template> util = new ExcelUtil<Template>(Template.class);
        util.exportExcel(response, list, "模板");
    }


    @PostMapping("/templateVerify")
    @Operation(summary = "模板校验")
    public R<TemplateVerifyVO> templateVerify(@RequestParam("file") MultipartFile file, @RequestParam("couponId") Long couponId) throws Exception {
        String fileName = file.getOriginalFilename();
        int lastIndexOfDot = fileName.lastIndexOf('.');
        String substring = fileName.substring(lastIndexOfDot + 1);
        if (lastIndexOfDot == -1 || !substring.equals("xlsx")) {
            return R.ok(null, "文件格式错误，请上传xlsx文件");
        }
        log.info("===================执行解析");
        ExcelReader reader = cn.hutool.poi.excel.ExcelUtil.getReader(file.getInputStream(), 0);
        log.info("===================执行解析成功");
        List<Object> objects1 = reader.readColumn(0, 1);
        log.info("=============读取成功");
        return marCouponDirectionalService.templateVerify(objects1, couponId);
    }

    /**
     * 添加到定向发放列表
     *
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/directionalAdd")
    @Operation(summary = "添加到定向发放列表")
    public R<Void> directionalAdd(@RequestParam("file") MultipartFile file, @RequestParam("couponId") Long couponId) throws Exception {
        ExcelUtil<Template> util = new ExcelUtil<Template>(Template.class);
        List<Template> list = util.importExcel(file.getInputStream());
        if (!list.isEmpty()) {
            List<String> mobiles = list.stream().map(s -> s.getMobile()).toList();
            if (mobiles.contains("内容格式错误")) {
                return R.ok(null, "内容格式错误！");
            }
            marCouponDirectionalService.directionalAdd(mobiles, couponId);
        }
        return R.ok();
    }


    /**
     * 定向发放列表
     *
     * @param marCouponDirectionalDTO
     * @return
     */
    @GetMapping("/directionalList")
    @Operation(summary = "定向发放列表")
    public R<TableDataInfo> directionalList(MarCouponDirectionalDTO marCouponDirectionalDTO) {
        startPage();
        List<MarCouponDirectionalVO> list = marCouponDirectionalService.directionalList(marCouponDirectionalDTO);
        TableDataInfo dataTable = getDataTable(list);
        return R.ok(dataTable);
    }


    /**
     * 定向批量发放优惠券
     *
     * @param couponId
     * @return
     */
    @PostMapping("/grantOrienteering")
    @Log(title = "pc-定向批量发放优惠券", businessType = BusinessType.INSERT)
    @Operation(summary = "定向批量发放优惠券")
    public R<Integer> grantOrienteering(Long couponId) {
        return marCouponDirectionalService.grantOrienteering(couponId);
    }


    @DeleteMapping("/deleteById")
    @Log(title = "pc-删除定向发放列表", businessType = BusinessType.DELETE)
    @Operation(summary = "删除定向发放列表")
    public R<Void> deleteById(Long id) {
        marCouponDirectionalService.deleteById(id);
        return R.ok();
    }

    @DeleteMapping("/directional/bulk/del")
    @Log(title = "pc-删除定向发放列表-一键删除", businessType = BusinessType.DELETE)
    @Operation(summary = "删除定向发放列表-一键删除")
    public R<Void> directionalBulkDel(Long couponId) {
        marCouponDirectionalService.bulkDelByMarCouponId(couponId);
        return R.ok();
    }


    @GetMapping("/prizeList")
    @Operation(summary = "抽奖奖励列表")
    public R<TableDataInfo> prizeList(PrizeVO prizeVO) {
        startPage();
        return R.ok(getDataTable(marCouponService.prizeList(prizeVO)));
    }

    @GetMapping("/disable")
    @Operation(summary = "禁用")
    public R<Void> disable(Long couponId) {
        marCouponService.disable(couponId);
        return R.ok();
    }


    /**
     * 全国优惠券
     * @param nationwideCouponDTO
     * @return
     */
    @GetMapping("/nationwideCoupon")
    @Operation(summary = "")
    public TableDataInfo nationwideCoupon(@RequestBody NationwideCouponDTO nationwideCouponDTO) {
        startPage();
        return getDataTable(marCouponService.nationwideCoupon(nationwideCouponDTO));
    }
}
